﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PACKETPARSERMAX20.CORE;

namespace PACKETPARSERMAX20.CONSOLE
{
    class Program
    {
        static void Main(string[] args)
        {
            var start = DateTime.Now;

            FindOpcodeInLog.ProcessSource(@"E:\Upload\WOWDEV\SNIFFS");

            //DBParserDump.GenerateCode();

            //FindOpcode();

            // ConvertBinToSQLite.ConvertFiles(@"H:\DATA\SQLITE\binary\", @"H:\DATA\SQLITE\dbs\");
            //ConvertOLDSQLiteToSQLite.Convert(@"E:\Upload\sort\", @"E:\Upload\NEW\");

            //ConvertOLDSQLiteToSQLite.Convert(@"E:\Upload\NEW\OLD\", @"E:\Upload\NEW\OLD_SORTED\");
             //OrganizeByClientBuild(@"E:\Upload\unknown\");

            //FindOpcodeItemQueryResponse();

            //ModbParserv1.Process(10505);

            //ModbParserv1.Process(11403);

            //ModbParser.DumpSigs(@".\sql\");

            //ModbParserv1.FixSQLs(@".\sql\");

            //@"F:\_SQLITE"
            //@"H:\DATA\SQLITE\dbs\"
            //DumpQueryDataToSQL(@"H:\DATA\SQLITE\dbs\");

            // DefinitionGen.Process();

            //DBParserDump.Process();

            //DBParserDump.Process(@"\\mikedb01\e\_SQLS\mangos_templates_dump\", "mangos_templates_dump");

            //DBParserDump.Process(@".\sqldump\", "mangos_templates_dump", true, true);


            //TableCodeGenerator.GenerateCode(true);

            //DumpQueryDataToSQL2(@"H:\DATA\SQLITE\dbs\");

           // TestAuras();

            var end = DateTime.Now - start;
            Console.WriteLine(string.Format("DONE! start: {0}, end: {1}", start, end));
            Console.WriteLine("enter any key to close console.");
            Console.ReadLine();
        }

        static void OrganizeByClientBuild(string pDir)
        {
            string[] tFileList = System.IO.Directory.GetFiles(pDir, "*.sqlite", System.IO.SearchOption.AllDirectories);

            EventManager eventManager = new EventManager();
            OpcodeFilter opcodeFilter = new OpcodeFilter();


            foreach (string tFile in tFileList)
            {
                DefinitionProcessor processor = DefinitionProcessor.LoadDefinitionProcessor(tFile, eventManager, opcodeFilter);
                if (processor != null)
                {
                    int build = processor.Reader.ClientBuild;
                    string dest = string.Format(pDir + @"{0}\", build);

                    if (!System.IO.Directory.Exists(dest))
                    {
                        System.IO.Directory.CreateDirectory(dest);
                    }

                    System.IO.File.Move(tFile, dest + System.IO.Path.GetFileName(tFile));
                }
            }
        }

        static void FindOpcode()
        {
            string[] tFileList = System.IO.Directory.GetFiles(@"H:\DATA\SQLITE\dbs\", "*.sqlite", System.IO.SearchOption.AllDirectories);

            var eventManager = new EventManager();
            var opcodeFilter = new OpcodeFilter();

            int i = 0;
            foreach (string tFile in tFileList)
            {
                var processor = DefinitionProcessor.LoadDefinitionProcessor(tFile, eventManager, opcodeFilter);
                if (processor != null)
                {
                    int build = processor.Reader.ClientBuild;
                    processor.Reader.MaxProcessCount = 5000000;

                    string query = string.Format("WHERE opcode IN ( {0}, {1}, {2}, {3}, {4})", 239, 240, 241, 812, 305);// "WHERE opcode = 305";

                    int count = processor.Reader.GetTotalByQuery(query);
                    if (count > 0)
                    {
                        query = string.Format("AND opcode IN ( {0}, {1}, {2}, {3}, {4})", 239, 240, 241, 812, 305);//"AND opcode = 305";

                        processor.Process(query);


                        i++;
                        System.Console.WriteLine(string.Format("{0} out of {1} {2} {3}", i, tFileList.Length, processor.Reader.FileName, build));
                    }
                }
            }
        }

        static void FindOpcodeItemQueryResponse()
        {
            string[] tFileList = System.IO.Directory.GetFiles(@"H:\DATA\SQLITE\dbs\9947\", "*.sqlite", System.IO.SearchOption.AllDirectories);

            EventManager eventManager = new EventManager();
            OpcodeFilter opcodeFilter = new OpcodeFilter();

            int i = 0;
            foreach (string tFile in tFileList)
            {
                DefinitionProcessor processor = DefinitionProcessor.LoadDefinitionProcessor(tFile, eventManager, opcodeFilter);
                if (processor != null)
                {
                    int build = processor.Reader.ClientBuild;
                    processor.Reader.MaxProcessCount = 5000000;

                    string query = string.Format("WHERE opcode IN ( {0}, {1})", 88, 89);// "WHERE opcode = 305";

                    int count = processor.Reader.GetTotalByQuery(query);
                    if (count > 0)
                    {
                        query = string.Format("AND opcode IN ( {0}, {1})", 88, 89);//"AND opcode = 305";

                        processor.Process(query);


                        i++;
                        System.Console.WriteLine(string.Format("{0} out of {1} {2} {3}", i, tFileList.Length, processor.Reader.FileName, build));
                    }
                }
            }
        }

        static void ProcessKNOCK_BACKData()
        {
            string[] tFileList = System.IO.Directory.GetFiles(@"H:\DATA\SQLITE\dbs\", "*.sqlite", System.IO.SearchOption.AllDirectories);

            EventManager eventManager = new EventManager();
            OpcodeFilter opcodeFilter = new OpcodeFilter();

            int i = 0;
            foreach (string tFile in tFileList)
            {
                DefinitionProcessor processor = DefinitionProcessor.LoadDefinitionProcessor(tFile, eventManager, opcodeFilter);
                if (processor != null)
                {
                    int build = processor.Reader.ClientBuild;
                    processor.Reader.MaxProcessCount = 5000000;

                    //SG_MOVE_KNOCK_BACK = 239,
                    //CMSG_MOVE_KNOCK_BACK_ACK = 240,
                    //MSG_MOVE_KNOCK_BACK = 241,
                    //CMSG_IGNORE_KNOCKBACK_CHEAT = 812,
                    string query = string.Format("WHERE opcode IN ( {0}, {1}, {2}, {3})", 239, 240, 241, 812);

                    int count = processor.Reader.GetTotalByQuery(query);
                    if (count > 0)
                    {
                        query = string.Format("AND opcode IN ( {0}, {1}, {2}, {3})", 239, 240, 241, 812);
                        processor.Process(query);
                        i++;
                        System.Console.WriteLine(string.Format("{0} out of {1} {2} {3}", i, tFileList.Length, processor.Reader.FileName, build));
                    }
                }
            }



        }

        static void ProcessGameObjectData()
        {
            string[] tFileList = System.IO.Directory.GetFiles(@"H:\DATA\SQLITE\dbs\", "*.sqlite", System.IO.SearchOption.AllDirectories);

            EventManager eventManager = new EventManager();
            OpcodeFilter opcodeFilter = new OpcodeFilter();

            int i = 0;
            foreach (string tFile in tFileList)
            {
                DefinitionProcessor processor = DefinitionProcessor.LoadDefinitionProcessor(tFile, eventManager, opcodeFilter);
                if (processor != null)
                {
                    int build = processor.Reader.ClientBuild;
                    processor.Reader.MaxProcessCount = 5000000;
                    processor.Process("AND opcode=" + ((int)Opcodes.SMSG_GAMEOBJECT_QUERY_RESPONSE).ToString());
                    i++;
                    System.Console.WriteLine(string.Format("{0} out of {1} {2} {3}", i, tFileList.Length, processor.Reader.FileName, build));
                }
            }

            System.Xml.XmlDocument tDom = new System.Xml.XmlDocument();
            tDom.AppendChild(tDom.CreateElement("GameObjects"));
            List<string> keylist = new List<string>();

            foreach (PACKETPARSERMAX20.CORE.GameObjectTemplateSum tObj in PACKETPARSERMAX20.CORE.GlobalCache.GameObjectTemplateSumList.Values)
            {
                string key = tObj.entry.ToString() + tObj.name + tObj.typeid.ToString();
                if (keylist.Contains(key)) continue;
                keylist.Add(key);
                System.Xml.XmlElement tElement = tDom.CreateElement("GameObject");
                tElement.SetAttribute("entry", tObj.entry.ToString());
                tElement.SetAttribute("name", tObj.name);
                tElement.SetAttribute("typeid", tObj.typeid.ToString());
                tDom.DocumentElement.AppendChild(tElement);
            }
            tDom.Save(".\\gameobjects.xml");
        }

        static void DumpQueryDataToSQL(string pSourceDir)
        {
            StringBuilder sb = new StringBuilder();

            //sb.Append(((int)Opcodes.SMSG_GAMEOBJECT_QUERY_RESPONSE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_CREATURE_QUERY_RESPONSE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_ITEM_QUERY_MULTIPLE_RESPONSE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_ITEM_QUERY_SINGLE_RESPONSE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_QUEST_QUERY_RESPONSE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_NPC_TEXT_UPDATE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_QUEST_POI_QUERY_RESPONSE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_QUEST_QUERY_RESPONSE).ToString());

            sb.Append(((int)Opcodes.SMSG_QUEST_POI_QUERY_RESPONSE).ToString());

            string[] dirs = System.IO.Directory.GetDirectories(pSourceDir);

            var orderdirs = (from t in dirs.AsEnumerable() orderby t descending select t);

            GlobalCache.writesql = true;
            GlobalCache.ignoreupdate = false;
            GlobalCache.ignoreinsert = false;

            foreach (string dir in orderdirs)
            {
                string[] files = System.IO.Directory.GetFiles(dir, "*.sqlite", System.IO.SearchOption.AllDirectories);

                EventManager eventManager = new EventManager();
                OpcodeFilter opcodeFilter = new OpcodeFilter();

                int i = 0;
                foreach (string file in files)
                {
                    DefinitionProcessor processor = DefinitionProcessor.LoadDefinitionProcessor(file, eventManager, opcodeFilter);
                    if (processor != null)
                    {
                        int build = processor.Reader.ClientBuild;
                        processor.Reader.MaxProcessCount = 5000000;
                        processor.Process("AND opcode in (" + sb.ToString() + ")");
                        i++;
                        System.Console.WriteLine(string.Format("{0} out of {1} {2} {3}", i, files.Length, processor.Reader.FileName, build));
                    }
                }
            }
        }

        static void DumpQueryDataToSQL2(string pSourceDir)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(((int)Opcodes.CMSG_AUTH_SESSION).ToString() + ",");
            sb.Append(((int)Opcodes.CMSG_PLAYER_LOGIN).ToString() + ",");
            sb.Append(((int)Opcodes.SMSG_AURA_UPDATE).ToString() + ",");
            sb.Append(((int)Opcodes.SMSG_AURA_UPDATE_ALL).ToString() + ",");
            sb.Append(((int)Opcodes.SMSG_COMPRESSED_UPDATE_OBJECT).ToString() + ",");
            sb.Append(((int)Opcodes.SMSG_UPDATE_OBJECT).ToString());

            //sb.Append(((int)Opcodes.SMSG_GAMEOBJECT_QUERY_RESPONSE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_CREATURE_QUERY_RESPONSE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_ITEM_QUERY_MULTIPLE_RESPONSE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_ITEM_QUERY_SINGLE_RESPONSE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_QUEST_QUERY_RESPONSE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_NPC_TEXT_UPDATE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_QUEST_POI_QUERY_RESPONSE).ToString() + ",");
            //sb.Append(((int)Opcodes.SMSG_QUEST_QUERY_RESPONSE).ToString());

            string[] dirs = System.IO.Directory.GetDirectories(pSourceDir);

            var orderdirs = (from t in dirs.AsEnumerable() orderby t descending select t);

            GlobalCache.writesql = false;
            GlobalCache.ignoreupdate = true;
            GlobalCache.ignoreinsert = true;

            foreach (string dir in orderdirs)
            {
                string[] files = System.IO.Directory.GetFiles(dir, "*.sqlite", System.IO.SearchOption.AllDirectories);

                EventManager eventManager = new EventManager();
                OpcodeFilter opcodeFilter = new OpcodeFilter();

                int i = 0;
                foreach (string file in files)
                {
                    DefinitionProcessor processor = DefinitionProcessor.LoadDefinitionProcessor(file, eventManager, opcodeFilter);
                    if (processor != null)
                    {
                        int build = processor.Reader.ClientBuild;
                        processor.Reader.MaxProcessCount = 5000000;
                        processor.Process("AND opcode in (" + sb.ToString() + ")");
                        i++;
                        System.Console.WriteLine(string.Format("{0} out of {1} {2} {3}", i, files.Length, processor.Reader.FileName, build));
                    }
                }
            }



            WriteAuras();

        }

        private static void WriteAuras()
        {
      
            MangosDatabase mangos = new MangosDatabase();
 
            var mangosidlist = mangos.ValidAuraSpellIDList();

            List<uint> verifyList = new List<uint>();
            StringBuilder sbverify = new StringBuilder();
            sbverify.Append("select id, name, description, actiontext from spell where id in (");
            foreach (var creatureaura in GlobalCache.creatureAuraList)
            {
                foreach (var aura in creatureaura.auralist)
                {
                    if (!mangosidlist.Contains(aura))
                        if (!verifyList.Contains(aura))
                        {
                            sbverify.Append(string.Format("{0},", aura));
                            verifyList.Add(aura);
                        }
                }
            }

            sbverify = sbverify.Replace(',', ' ', sbverify.Length - 1, 1);
            sbverify.Append(") order by id;");

            using (System.IO.StreamWriter sw = new System.IO.StreamWriter(".\\verifyauraslist_new.sql"))
            {
                //sw.Write(Serializer.ToXml(GlobalCache.creatureAuraList, GlobalCache.creatureAuraList.GetType()));
                sw.Write(sbverify);
                sw.Close();
            }

            using (System.IO.StreamWriter sw = new System.IO.StreamWriter(".\\aurasbyentry_new.xml"))
            {
                sw.Write(Serializer.ToXml(GlobalCache.creatureAuraList, GlobalCache.creatureAuraList.GetType()));
                sw.Close();
            }
        }

        private static void TestAuras()
        {

            using (System.IO.StreamReader sr = new System.IO.StreamReader(".\\aurasbyentry2.xml"))
            {
                GlobalCache.creatureAuraList = (CreatureAuraList)Serializer.FromXml(sr.ReadToEnd(), typeof(CreatureAuraList));
                sr.Close();
            }

            DBCDatabase dbc = new DBCDatabase("dbc_333", true);
            MangosDatabase mangos = new MangosDatabase();

            var dbcidlist = dbc.ValidAuraSpellIDList();
            var mangosidlist = mangos.ValidAuraSpellIDList();

            //StringBuilder sbmangos = new StringBuilder();
            //sbmangos.Append("select id, name, description, actiontext from spell where id in (");
            //foreach (var aura in mangosidlist)
            //{
            //    sbmangos.Append(string.Format("{0},", aura));
            //}

            //sbmangos = sbmangos.Replace(',', ' ', sbmangos.Length - 1, 1);
            //sbmangos.Append(") order by id;");

            GlobalCache.creatureAuraList.ForEach(t => t.auralist.RemoveAll(s => !dbcidlist.Contains(s) || s == 0));
            GlobalCache.creatureAuraList.RemoveAll(t => t.auralist.Count == 0);

            List<uint> verifyList = new List<uint>();
            StringBuilder sbverify = new StringBuilder();
            sbverify.Append("select id, name, description, actiontext from spell where id in (");
            foreach (var creatureaura in GlobalCache.creatureAuraList)
            {
                foreach (var aura in creatureaura.auralist)
                {
                    if (!mangosidlist.Contains(aura))
                        if (!verifyList.Contains(aura))
                        {
                            sbverify.Append(string.Format("{0},", aura));
                            verifyList.Add(aura);
                        }
                }
            }

            sbverify = sbverify.Replace(',', ' ', sbverify.Length - 1, 1);
            sbverify.Append(") order by id;");

            using (System.IO.StreamWriter sw = new System.IO.StreamWriter(".\\verifyauraslist.sql"))
            {
                //sw.Write(Serializer.ToXml(GlobalCache.creatureAuraList, GlobalCache.creatureAuraList.GetType()));
                sw.Write(sbverify);
                sw.Close();
            }

            //StringBuilder sb = new StringBuilder();
            //List<uint> listed = new List<uint>();

            //sb.Append("select id, name, description, actiontext from spell where id in (");
            //foreach (CreatureAuraList.CreatureAura creatureaura in GlobalCache.creatureAuraList)
            //{
            //    foreach(uint id in creatureaura.auralist)
            //    {
            //        if (!listed.Contains(id))
            //        {
            //            sb.Append(string.Format("{0},", id));

            //            listed.Add(id);
            //        }
            //    }
            //}

            //sb = sb.Replace(',', ' ', sb.Length - 1, 1);
            //sb.Append(") order by id;");

            //Console.WriteLine(sb.ToString());


            using (System.IO.StreamWriter sw = new System.IO.StreamWriter(".\\aurasbyentry2.xml"))
            {
                sw.Write(Serializer.ToXml(GlobalCache.creatureAuraList, GlobalCache.creatureAuraList.GetType()));
                sw.Close();
            }

        }

    }
}
